package com.md.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;








import org.apache.commons.lang3.StringUtils;

public class DataUtils {

	public static final String[] EMPTY_STRING_ARRAY = new String[0];

	public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

	public static final String[] CN_UPPER_NUMBER = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };

	public static final String LINE_SEPARATOR = System.getProperty("line.separator");

	public static String generateUUID() {
		String uuid = UUID.randomUUID().toString();
		return uuid.substring(0, 8) + uuid.substring(9, 13) + uuid.substring(14, 18) + uuid.substring(19, 23)
				+ uuid.substring(24);
	}

	/**
	 * 生成随机数（4位：0001~9999）
	 * 
	 * @param pos
	 *            随机数的位数
	 * @return
	 */
	public static String getRandomNumber(int pos) {
		StringBuilder prefixBuilder = new StringBuilder();
		long randomNumber = (System.currentTimeMillis() % (int) Math.pow(10, pos - 1));
		for (int i = pos; i > 0; i--) {
			if (randomNumber / (int) Math.pow(10, i - 1) == 0) {
				prefixBuilder.append("0");
			} else {
				break;
			}
		}
		return prefixBuilder.toString() + randomNumber;
	}

	/**
	 * 返回两个对象是否相等。<br />
	 * 允许传空。
	 * 
	 * @param o1
	 *            对象1。
	 * @param o2
	 *            对象2。
	 * 
	 * @return 两个对象是否相等。
	 */
	public static boolean isEquals(Object o1, Object o2) {
		return o1 == null ? o2 == null : o1.equals(o2);
	}

	/**
	 * 判断目标对象是否为空。
	 * 
	 * <pre>
	 * DataUtils.isBlank(null)      = true
	 * DataUtils.isBlank("")        = true
	 * DataUtils.isBlank(" ")       = true
	 * DataUtils.isBlank("bob")     = false
	 * DataUtils.isBlank(new ArrayList()) = true
	 * DataUtils.isBlank(new String[1]) = true
	 * </pre>
	 * 
	 * @param o
	 *            目标对象。
	 * @return 目标对象是否为空。
	 */
	public static boolean isBlank(Object o) {
		if (o == null) {
			return true;
		}

		if (o instanceof String) {
			return isBlankCharSequence((String) o);
		} else if (o instanceof Collection) {
			return ((Collection<?>) o).isEmpty();
		} else if (o instanceof Map) {
			return ((Map<?, ?>) o).isEmpty();
		} else if (o instanceof Object[]) {
			return ((Object[]) o).length == 0;
		}

		return false;
	}

	/**
	 * 将首字母转换为大写。
	 * 
	 * <pre>
	 * StringUtils.capitalize(null)  = null
	 * StringUtils.capitalize("")    = ""
	 * StringUtils.capitalize("cat") = "Cat"
	 * StringUtils.capitalize("cAt") = "CAt"
	 * </pre>
	 * 
	 * @param str
	 *            目标字符串，可为空。
	 * @return 首字母转换为大写后的字符串。
	 */
	public static String capitalize(final String str) {
		int strLen;
		if (str == null || (strLen = str.length()) == 0) {
			return str;
		}

		char firstChar = str.charAt(0);
		if (Character.isTitleCase(firstChar)) {
			// 已经是首字母大写。
			return str;
		}

		return new StringBuilder(strLen).append(Character.toTitleCase(firstChar)).append(str.substring(1)).toString();
	}

	/**
	 * 将字符串首字母转换为小写。
	 * 
	 * <pre>
	 * StringUtils.uncapitalize(null)  = null
	 * StringUtils.uncapitalize("")    = ""
	 * StringUtils.uncapitalize("Cat") = "cat"
	 * StringUtils.uncapitalize("CAT") = "cAT"
	 * </pre>
	 * 
	 * @param str
	 *            目标字符串，可为空。
	 * @return 首字母转换为小写后的字符串。
	 */
	public static String uncapitalize(final String str) {
		int strLen;
		if (str == null || (strLen = str.length()) == 0) {
			return str;
		}

		char firstChar = str.charAt(0);
		if (Character.isLowerCase(firstChar)) {
			// 已经是首字母小写。
			return str;
		}

		return new StringBuilder(strLen).append(Character.toLowerCase(firstChar)).append(str.substring(1)).toString();
	}

	/**
	 * 将2进制转换为16进制。
	 * 
	 * @param buf
	 *            2进制byte数组。
	 * @return 16进制字符串。
	 */
	public static String byteToHex(byte buf[]) {
		StringBuilder builder = new StringBuilder();
		String hex = null;
		for (int i = 0; i < buf.length; i++) {
			hex = Integer.toHexString(buf[i] & 0xFF);
			if (hex.length() == 1) {
				builder.append('0');
				builder.append(hex);
			} else {
				builder.append(hex);
			}
		}
		return builder.toString();
	}

	/**
	 * 将16进制转换为二进制。
	 * 
	 * @param hexStr
	 *            16进制字符串。
	 * @return 2进制byte数组。
	 */
	public static byte[] hexToByte(String hexStr) {
		if (hexStr.length() < 1) {
			return null;
		}
		byte[] result = new byte[hexStr.length() / 2];
		int high = -1;
		int low = -1;
		for (int i = 0; i < hexStr.length() / 2; i++) {
			high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
			low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
			result[i] = (byte) (high * 16 + low);
		}
		return result;
	}

	/**
	 * 判断目标字符序列是否为空。
	 * 
	 * @param cs
	 *            目标字符序列。
	 * @return 目标序列是否为空。
	 */
	private static boolean isBlankCharSequence(final CharSequence cs) {
		int strLen;
		if (cs == null || (strLen = cs.length()) == 0) {
			return true;
		}
		for (int i = 0; i < strLen; i++) {
			if (Character.isWhitespace(cs.charAt(i)) == false) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 将字符串转为unicode
	 */
	public static String toUnicodeString(String gbString) {
		char[] utfBytes = gbString.toCharArray();
		String unicodeBytes = "";
		for (int byteIndex = 0; byteIndex < utfBytes.length; byteIndex++) {
			String hexB = Integer.toHexString(utfBytes[byteIndex]);
			if (hexB.length() <= 2) {
				hexB = "00" + hexB;
			}
			unicodeBytes = unicodeBytes + "\\u" + hexB;
		}
		return unicodeBytes;
	}

	/**
	 * 判断是否是数字<br>
	 * 包括小数
	 */
	public static boolean isNumber(String number) {
		if (number == null) {
			return false;
		}

		int index = number.indexOf(".");
		if (index < 0) {
			if (number.charAt(0) == '-') {
				return StringUtils.isNumeric(number.substring(1, number.length()));
			} else {
				return StringUtils.isNumeric(number);
			}
		} else {
			String num1 = number.substring(0, index);
			String num2 = number.substring(index + 1);

			return StringUtils.isNumeric(num1) && StringUtils.isNumeric(num2);
		}
	}

	/**
	 * 数据集合转‘,’分割的字符串<br>
	 * 查询数据库拼字符串使用
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String arrayToString(Object obj) {
		Collection<String> collection = null;
		if (DataUtils.isBlank(obj)) {
			return null;
		}
		StringBuilder stringBuilder = new StringBuilder();
		if (obj instanceof Collection) {
			collection = (Collection<String>) obj;
			for (String id : collection) {
				stringBuilder.append("'");
				stringBuilder.append(id);
				stringBuilder.append("',");
			}
			stringBuilder.deleteCharAt(stringBuilder.length() - 1);
			return stringBuilder.toString();
		} else {
			throw new RuntimeException();
		}
	}

	/**
	 * 正则统计字符串出现次数Map形式
	 *
	 * @param source
	 *
	 * @param regexNew
	 * @return Map(总数： amount, 各自的数目：each, 有序全数据：orderlyList )
	 */
	public static Map<String, Object> regexFinder(String source, String regex) {
		TreeMap<Object, Integer> myTreeMap = new TreeMap<Object, Integer>();
		TreeMap<String, Object> resultMap = new TreeMap<String, Object>();
		List<Object> orderlyList = new ArrayList<Object>();
		if (regex == null || regex.equals("")) {
			return null;
		}
		Pattern expression = Pattern.compile(regex);
		Matcher matcher = expression.matcher(source);
		int n = 0;
		Object word = null;
		Object num = null;
		while (matcher.find()) {
			word = matcher.group();
			orderlyList.add(word);
			n++;
			if (myTreeMap.containsKey(word)) {
				num = myTreeMap.get(word);
				Integer count = (Integer) num;
				myTreeMap.put(word, new Integer(count.intValue() + 1));
			} else {
				myTreeMap.put(word, new Integer(1));
			}
		}
		resultMap.put("amount", n);
		resultMap.put("each", myTreeMap);
		resultMap.put("orderlyList", orderlyList);

		return resultMap;
	}

	/** 通过 yyyy-MM-dd 得到中文大写格式 yyyy MM dd 日期 */
	public static synchronized String toChinese(String str) {
		StringBuffer sb = new StringBuffer();
		sb.append(getSplitDateStr(str, 0)).append(" ").append(getSplitDateStr(str, 1)).append(" ")
				.append(getSplitDateStr(str, 2));
		return sb.toString();
	}

	/**
	 * 分别得到年月日的大写 默认分割符 "-"
	 * 
	 * @param str
	 *            日期字符串
	 * @param unit
	 *            计算单位 0=年 1=月 2日
	 * @return
	 */
	public static String getSplitDateStr(String str, int unit) {
		// unit是单位 0=年 1=月 2日
		String[] DateStr = str.split("-");
		String value = "";
		if (unit > DateStr.length)
			unit = 0;
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < DateStr[unit].length(); i++) {

			if ((unit == 1 || unit == 2) && Integer.valueOf(DateStr[unit]) > 9) {
				sb.append(convertNum(DateStr[unit].substring(0, 1))).append("壹拾")
						.append(convertNum(DateStr[unit].substring(1, 2)));
				break;
			} else {
				sb.append(convertNum(DateStr[unit].substring(i, i + 1)));
			}
		}
		value = sb.toString();
		if (sb.toString().endsWith("零")) {
			value = value.substring(0, sb.toString().length() - 1);
		}
		if (unit == 1) {
			return value.replaceAll("^壹", "");
		}
		if (unit == 2) {
			if (value.split("壹").length > 1) {
				return value.replaceFirst("壹", "");
			}
			return value.replaceAll("^壹", "");
		}
		return value;

	}

	/** 转换数字为大写 */
	private static String convertNum(String str) {
		return CN_UPPER_NUMBER[Integer.valueOf(str)];
	}

	/**
	 * 金额计算（数字转中文大写）
	 * 
	 * @param num
	 * 
	 * @param enabledMoney
	 *            是否启用金额计算(若启用则会有整、角、分)
	 * @return
	 */
	public static String NumToChinese(double num, boolean enabledMoney) {
		if (num > 99999999999999.99 || num < -99999999999999.99)
			throw new IllegalArgumentException("参数值超出允许范围 (-99999999999999.99 ～ 99999999999999.99)！");
		boolean negative = false;// 正负标号
		if (num < 0) {
			negative = true;
			num = num * (-1);
		}
		long temp = Math.round(num * 100);
		int numFen = (int) (temp % 10);// 分
		temp = temp / 10;
		int numJiao = (int) (temp % 10);// 角
		temp = temp / 10;
		// 此时temp只包含整数部分
		int[] parts = new int[20];// 将金额整数部分分为在0-9999之间数的各个部分
		int numParts = 0;// 记录把原来金额整数部分分割为几个部分
		for (int i = 0;; i++) {
			if (temp == 0)
				break;
			int part = (int) (temp % 10000);
			parts[i] = part;
			temp = temp / 10000;
			numParts++;
		}
		boolean beforeWanIsZero = true;// 标志位，记录万的下一级是否为0
		String chineseStr = "";
		for (int i = 0; i < numParts; i++) {
			String partChinese = partConvert(parts[i]);
			if (i % 2 == 0) {
				if ("".equals(partChinese))
					beforeWanIsZero = true;
				else
					beforeWanIsZero = false;
			}
			if (i != 0) {
				if (i % 2 == 0)// 亿的部分
					chineseStr = "亿" + chineseStr;
				else {
					if ("".equals(partChinese) && !beforeWanIsZero)// 如果“万”对应的
																	// part 为
																	// 0，而“万”下面一级不为
																	// 0，则不加“万”，而加“零”
						chineseStr = "零" + chineseStr;
					else {
						if (parts[i - 1] < 1000 && parts[i - 1] > 0)// 如果万的部分不为0，而万前面的部分小于1000大于0，则万后面应该跟零
							chineseStr = "零" + chineseStr;
						chineseStr = "万" + chineseStr;
					}
				}
			}
			chineseStr = partChinese + chineseStr;
		}
		if ("".equals(chineseStr))// 整数部分为0，则表示为零元
			chineseStr = CN_UPPER_NUMBER[0];
		else if (negative)// 整数部分部位0，但是为负数
			chineseStr = "负" + chineseStr;
		if (enabledMoney) {
			chineseStr = chineseStr + "元";
		}
		if (numFen == 0 && numJiao == 0 && enabledMoney) {
			chineseStr = chineseStr + "整";
		} else if (numFen == 0 && enabledMoney) {// 0分
			chineseStr = chineseStr + CN_UPPER_NUMBER[numJiao] + "角";
		} else {
			if (numJiao == 0 && enabledMoney)
				chineseStr = chineseStr + "零" + CN_UPPER_NUMBER[numFen] + "分";
			else if (enabledMoney)
				chineseStr = chineseStr + CN_UPPER_NUMBER[numJiao] + "角" + CN_UPPER_NUMBER[numFen] + "分";
		}
		return chineseStr;
	}

	// 转换拆分后的每个部分，0-9999之间
	public static String partConvert(int partNum) {
		if (partNum < 0 || partNum > 10000) {
			throw new IllegalArgumentException("参数必须是大于等于0或小于10000的整数");
		}
		String[] units = new String[] { "", "拾", "佰", "仟" };
		int temp = partNum;
		String partResult = new Integer(partNum).toString();
		int partResultLength = partResult.length();
		boolean lastIsZero = true;// 记录上一位是否为0
		String chineseStr = "";
		for (int i = 0; i < partResultLength; i++) {
			if (temp == 0)// 高位无数字
				break;
			int digit = temp % 10;
			if (digit == 0) {
				if (!lastIsZero)// 如果前一个数字不是0则在当前汉字串前加零
					chineseStr = "零" + chineseStr;
				lastIsZero = true;
			} else {
				chineseStr = CN_UPPER_NUMBER[digit] + units[i] + chineseStr;
				lastIsZero = false;
			}
			temp = temp / 10;
		}
		return chineseStr;
	}

	/**
	 * list 结构 转换成 map结构。<br>
	 * 关键字key 为 更新标识<br>
	 * such as : <br>
	 * [{key:1,name:'aa'},{key:1,name:'bb'},{key:2,name:'cc'}] <br>
	 * ---> <br>
	 * {1:[{key:1,name:'aa'},{key:1,name:'bb'}],2:{key:2,name:'cc'}}
	 * 
	 * @param key
	 * @param map
	 * @param list
	 */
	public static void listConverToMap(String key, Map map, List list) {
		Object obj = null;
		List<Map<String, Object>> tmpList = null;
		Map<String, Object> recordMap = null;
		for (Object record : list) {
			recordMap = (Map<String, Object>) record;
			obj = map.get(recordMap.get(key));
			if (obj == null) {
				tmpList = new ArrayList<Map<String, Object>>();
				map.put((String) recordMap.get(key), tmpList);
			} else {
				tmpList = (List<Map<String, Object>>) obj;
			}
			tmpList.add(recordMap);
		}
	}

	/**
	 * list to INFilter sql<br>
	 * list 结构转换成逗号拼接的sql片段，应用于in sql片段场景<br>
	 * 例如 ： ids :['1','2','3']--> '1','2','3'
	 */
	public static String listToInSqlWhereClause(List<String> ids) {
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("'null',");
		for (String id : ids) {
			stringBuilder.append("'");
			stringBuilder.append(id);
			stringBuilder.append("',");
		}
		stringBuilder.deleteCharAt(stringBuilder.length() - 1);
		return stringBuilder.toString();
	}
	
	/**
	 * JavaBean转换为Map  
	 * @author yehao
	 * @param clazz
	 * @param bean
	 * @return
	 * @throws Exception
	 */
	public static Map<String,Object> bean2map(Class<?> clazz , Object bean) throws Exception{  
	    Map<String,Object> map = new HashMap<>();  
	    //获取指定类（Person）的BeanInfo 对象  
	    BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);  
	    //获取所有的属性描述器  
	    PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();  
	    for(PropertyDescriptor pd:pds){  
	        String key = pd.getName();  
	        Method getter = pd.getReadMethod();  
	        Object value = getter.invoke(bean);  
	        map.put(key, value);  
	    }  
	    return map;  
	}  
	
	/**
	 * Map转换为JavaBean  
	 * @author yehao
	 * @param map
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public static <T> T map2bean(Map<String,Object> map,Class<T> clz) throws Exception{  
	    //创建JavaBean对象  
	    T obj = clz.newInstance();  
	    //获取指定类的BeanInfo对象  
	    BeanInfo beanInfo = Introspector.getBeanInfo(clz, Object.class);  
	    //获取所有的属性描述器  
	    PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();  
	    for(PropertyDescriptor pd:pds){  
	        Object value = map.get(pd.getName());  
	        Method setter = pd.getWriteMethod();  
	        setter.invoke(obj, value);  
	    }  
	      
	    return  obj;  
	}  
}
